import math
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns 
from IPython.display import display


def plot_distribution(dataset,width=20,heigth=160,cols=3,hspace=0.5,wspace=0.5):
    fig = plt.figure(figsize=(width,heigth))
    rows = math.ceil(dataset.shape[1]/cols)
    fig.subplots_adjust(hspace=hspace,wspace=wspace)
    for i,column in enumerate(dataset.columns):
        ax = fig.add_subplot(rows,cols,i+1)
        ax.set_title(column)
        if dataset.dtypes[column] == 'object':
            sns.countplot(data=dataset,x=column,ax=ax)
        else:
            sns.histplot(data=dataset,kde=True,x=column,ax=ax)
        plt.xticks(rotation=25)

def plot_bar_with_line_chart(data, x_var, y_var, group_var=None, 
                             agg_func='sum', 
                             figsize=(14, 8),
                             title=None, 
                             x_label=None, 
                             y_label=None, 
                             line_label='Average Value',
                             palette='viridis',
                             line_color='red',
                             sort_bars=True): # 新增：排序开关参数
    """
    绘制一个组合图表：垂直柱状图展示分组聚合值，同一X轴上的折线图展示每个X类别的均值。
    柱状图默认按降序排序。

    参数:
    ... (其他参数同上)
    sort_bars (bool): 是否按柱状图的总值对X轴进行降序排序。默认为True。
    """
    # 数据准备
    plot_data = data.copy()
    
    if group_var is None:
        plot_data['_temp_group_'] = 'All'
        group_var_for_plot = '_temp_group_'
    else:
        group_var_for_plot = group_var

    # 1. 聚合数据用于柱状图
    agg_data = plot_data.groupby([x_var, group_var_for_plot])[y_var].agg(agg_func).reset_index()
    
    # 2. 计算每个X类别的均值用于折线图
    mean_data = plot_data.groupby(x_var)[y_var].mean().reset_index()
    mean_data.rename(columns={y_var: 'mean_value'}, inplace=True)

    # --- 新增排序逻辑 ---
    if sort_bars:
        # 计算每个x_var类别的总值
        total_by_x = agg_data.groupby(x_var)[y_var].sum().reset_index()
        # 按总值降序排序，获取排序后的x_var类别列表
        sorted_order = total_by_x.sort_values(by=y_var, ascending=False)[x_var].tolist()
    else:
        # 如果不排序，则使用原始数据中的类别顺序
        sorted_order = agg_data[x_var].unique().tolist()

    # --- 绘图 ---
    fig, ax1 = plt.subplots(figsize=figsize)

    # --- Y轴1: 柱状图 ---
    # 在sns.barplot中使用 'order' 参数来应用排序
    sns.barplot(data=agg_data, x=x_var, y=y_var, hue=group_var_for_plot, 
                order=sorted_order, palette=palette, ax=ax1)

    # --- 添加柱状图数值标签 ---
    y_max_bar = agg_data[y_var].max()
    for p in ax1.patches:
        height = p.get_height()
        ax1.text(p.get_x() + p.get_width() / 2., height + y_max_bar * 0.01,
                 f'{height:,.2f}', ha='center', va='bottom', fontsize=10)

    # --- Y轴2: 折线图 ---
    ax2 = ax1.twinx()
    # 确保折线图的数据顺序与排序后的柱状图一致
    mean_data_sorted = mean_data.set_index(x_var).reindex(sorted_order).reset_index()
    sns.lineplot(data=mean_data_sorted, x=x_var, y='mean_value', marker='o', 
                 color=line_color, linewidth=2, ax=ax2, label=line_label)
    
    # --- 图表美化 ---
    ax1.set_title(title if title else f'{agg_func.capitalize()} and Mean of {y_var} by {x_var}', fontsize=16)
    ax1.set_xlabel(x_label if x_label else x_var, fontsize=12)
    ax1.set_ylabel(y_label if y_label else y_var, fontsize=12)
    ax2.set_ylabel(f'Average {y_var}', fontsize=12)

    # 图例
    handles1, labels1 = ax1.get_legend_handles_labels()
    handles2, labels2 = ax2.get_legend_handles_labels()
    ax1.legend(handles1 + handles2, labels1 + labels2, title='Legend', 
               title_fontsize=12, fontsize=10, loc='center right')
    
    plt.tight_layout()
    plt.show()


    # print("--- 图表1: 按销售额降序排序 ---")
    # plot_bar_with_line_chart(
    #     data=df_and_rfm_df,
    #     x_var='Customer Type',
    #     y_var='Sales',
    #     # group_var=None,
    #     agg_func='sum',
    #     title='Sales Volume and Average Sales by Product Category (Sorted)',
    #     x_label='Product Category',
    #     y_label='Total Sales',
    #     line_label='Average Sales per Order'
    # )


    # # --- 4. 另一个调用示例 (有分组，更复杂的场景) ---
    # print("\n--- 图表2: 有分组示例 (按月份) ---")
    # plot_bar_with_line_chart(
    #     data=df_and_rfm_df,
    #     x_var='Months',
    #     y_var='Sales',
    #     group_var='Customer Type', # 按客户类型分组
    #     agg_func='sum',
    #     title='Monthly Sales and Average Order Value by Customer Type',
    #     x_label='Month',
    #     y_label='Total Monthly Sales',
    #     line_label='Average Order Value'
    # )